#ifndef LOADEROBJ_H
#define LOADEROBJ_H

#include "Export.h"
#include "ILoader.h"
#include "Mesh.h"
#include <string>
#include <iostream>
#include <fstream>

namespace glow 
{
  class SHARED LoaderOBJ : public ILoader<Mesh_data>
  {

  public :
    Mesh_data *load (std::string filename.c_str())
    {
      Mesh_data * Mp =new Mesh_data;     

      Mp->_nb_vertices = Mp->_nb_texcoord = Mp->_nb_normals = Mp->_nb_index = 0;
      _indiceObj = Mp->_index = NULL;
      _posObj = _texObj = _norObj = NULL;

      count(filename.c_str());

      int cpt = 1, d = 0;

      _posObj = new float[Mp->_nb_vertices];
      if(Mp->_nb_texcoord)
	{
	  _texObj = new float[Mp->_nb_texcoord];
	  cpt++;
	}
      if(Mp->_nb_normals)
	{
	  _norObj = new float[Mp->_nb_normals];
	  cpt++;
	}

      d = Mp->_nb_index/cpt;

      _indiceObj = new unsigned int[Mp->_nb_index];
      Mp->_index = new unsigned int[d];

      Mp->_vertices = new float[d*3];
      if(Mp->_nb_texcoord) _texcoord = new float[d*2];
      if(Mp->_nb_normals) Mp->_normals = new float[d*3];

      fill(filename.c_str());

      unsigned int index = 0;
      for(unsigned int i=0; i<Mp->_nb_index;)
	{
	  Mp->_index[index] = index;

	  Mp->_vertices[index*3] = _posObj[(_indiceObj[i]-1)*3];
	  Mp->_vertices[index*3+1] = _posObj[(_indiceObj[i]-1)*3+1];
	  Mp->_vertices[index*3+2] = _posObj[(_indiceObj[i]-1)*3+2];
	  i++;
	  if(Mp->_nb_texcoord)
	    {
	      Mp->_texcoord[index*2] = _texObj[(_indiceObj[i]-1)*2];
	      Mp->_texcoord[index*2+1] = _texObj[(_indiceObj[i]-1)*2+1];
	      i++;
	    }
	  if(Mp->_nb_normals)
	    {
	      Mp->_normals[index*3] = _norObj[(_indiceObj[i]-1)*3];
	      Mp->_normals[index*3+1] = _norObj[(_indiceObj[i]-1)*3+1];
	      Mp->_normals[index*3+2] = _norObj[(_indiceObj[i]-1)*3+2];
	      i++;
	    }
	  index++;
	}

      if(_posObj) delete[] _posObj;
      if(_texObj) delete[] _texObj;
      if(_norObj) delete[] _norObj;
      if(_indiceObj) delete[] _indiceObj;

      return Mp;
    }

  private:
    unsigned int *_indiceObj;
    float *_posObj, *_texObj, *_norObj;

    void count (std::string filename.c_str())
    {
      Mp->_nb_vertices = Mp->_nb_texcoord = Mp->_nb_normals = Mp->_nb_index = 0;
      ifstream file(filename.c_str(), ios::in);
      if(file)
	{
	  std::string key;
	  file >> key;
	  while(!file.eof())
	    {
	      if(key == "v")
                Mp->_nb_vertices+=3;
	      else if(key == "vt")
                Mp->_nb_texcoord+=2;
	      else if(key == "vn")
                Mp->_nb_normals+=3;
	      else if(key == "f")
		{
		  if(Mp->_nb_vertices) Mp->_nb_index+=3;
		  if(Mp->_nb_texcoord) Mp->_nb_index+=3;
		  if(Mp->_nb_normals) Mp->_nb_index+=3;
		}
	      file >> key;
	    }
	  file.close();
	}
      else
        throw LoadingFailed(filename.c_str(), "Couldn't open file.");
    }

    void fill (std::string filename.c_str())
    {
      char s;
      ifstream file(filename.c_str(), ios::in);
      if(file)
	{
	  Mp->_nb_vertices = Mp->_nb_texcoord = Mp->_nb_normals = Mp->_nb_index = 0;
	  std::string key;
	  file >> key;
	  while(!file.eof())
	    {
	      if(key == "v")
		{
		  file >> _posObj[Mp->_nb_vertices] >> _posObj[Mp->_nb_vertices+1] >> _posObj[Mp->_nb_vertices+2];
		  Mp->_nb_vertices+=3;
		}
	      else if(key == "vt")
		{
		  file >> _texObj[Mp->_nb_texcoord] >> _texObj[Mp->_nb_texcoord+1];
		  Mp->_nb_texcoord+=2;
		}
	      else if(key == "vn")
		{
		  file >> _norObj[Mp->_nb_normals] >> _norObj[Mp->_nb_normals+1] >> _norObj[Mp->_nb_normals+2];
		  Mp->_nb_normals+=3;
		}
	      else if(key == "f")
		{
		  for(int i=0; i<3; i++)
		    {
		      file >> _indiceObj[Mp->_nb_index];
		      Mp->_nb_index++;
		      if(Mp->_texcoord)
			{
			  file.get(s);
			  file >> _indiceObj[Mp->_nb_index];
			  Mp->_nb_index++;
			}
		      if(Mp->_normals)
			{
			  file.get(s);
			  if(!Mp->_texcoord) file.get(s);
			  file >> _indiceObj[Mp->_nb_index];
			  Mp->_nb_index++;
			}
		    }
		}
	      file >> key;
	    }
	  file.close();
	}
      else
        throw LoadingFailed(filename.c_str(), "Couldn't open file.");
    }

  };
}
#endif
